﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using WPFClient.Codes;

namespace WPFClient.Views
{
    /// <summary>
    /// RollerView.xaml 的交互逻辑
    /// </summary>
    public partial class RollerView : UserControl
    {
        private ObservableCollection<RollerPLCProtocolMessage> _plcDataList;
        private TCPHelper _tcpHelper;
        private const int MAX_ITEMS = 100;
        private const int MAX_LOG_LINES = 200; // 日志最大行数
        private const int RECONNECT_INTERVAL = 2000; // 2秒重连间隔

        // 连接状态管理
        private bool _isConnected = false;
        private bool _shouldReconnect = false;
        private CancellationTokenSource _reconnectCancellationTokenSource;

        public RollerView()
        {
            InitializeComponent();
            InitData();
            Button_Click(null, null);

            // 统一资源清理
            this.Unloaded += (sender, args) =>
            {
                _shouldReconnect = false;
                _reconnectCancellationTokenSource?.Cancel();
                Cleanup();
            };
        }

        private async void Button_Click(object sender, RoutedEventArgs e)
        {
            // 开始连接
            _shouldReconnect = true;

            await StartConnection();
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            // 断开连接
            _shouldReconnect = false;
            _reconnectCancellationTokenSource?.Cancel();

            Cleanup();
            AddLog("连接已手动断开。");
        }

        private void languageChangeComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (languageChangeComboBox.SelectedItem is LanguageInfo selectedLanguage)
            {
                // 跳过"请选择语言"选项
                if (string.IsNullOrEmpty(selectedLanguage.LanguageCode))
                    return;

                try
                {
                    GlobalObject.CurrentLanguageManager.SetLanguage(selectedLanguage.LanguageCode);

                    AddLog($"语言已切换为: {selectedLanguage.DisplayName}");
                }
                catch (Exception ex)
                {
                    AddLog(new Exception($"语言切换失败: {ex.Message}", ex));
                    // 如果切换失败，回滚到默认语言
                    languageChangeComboBox.SelectedIndex = 1;
                }
            }
        }

        #region 初始化界面基础数据

        private void InitData()
        {
            _plcDataList = new ObservableCollection<RollerPLCProtocolMessage>();
            deviceDataGrid.ItemsSource = _plcDataList;

            List<LanguageInfo> languages = new List<LanguageInfo>
            {
                new LanguageInfo { DisplayName = "请选择语言", LanguageCode = "" },
                new LanguageInfo { DisplayName = "简体中文", LanguageCode = LanguageManager.Chinese },
                new LanguageInfo { DisplayName = "English", LanguageCode = LanguageManager.English },
                new LanguageInfo { DisplayName = "Albanian", LanguageCode = LanguageManager.Albanian }
            };

            languageChangeComboBox.ItemsSource = languages;
            languageChangeComboBox.SelectedIndex = 1; // 默认选中简体中文
        }

        #endregion

        #region 开始PLC设备的链接

        private async Task StartConnection()
        {
            // 取消之前的重连尝试
            _reconnectCancellationTokenSource?.Cancel();

            int reconnectInterval = 2;

            while (_shouldReconnect)
            {
                try
                {
                    string ip = ConfigHelper.GetConfigValue("$.PLCMachine.PLC1.IP");
                    string port = ConfigHelper.GetConfigValue("$.PLCMachine.PLC1.Port");
                    string reconnectIntervalStr = ConfigHelper.GetConfigValue("$.PLCMachine.PLC1.ReconnectInterval");

                    if (!string.IsNullOrEmpty(reconnectIntervalStr) && int.TryParse(reconnectIntervalStr, out int configInterval))
                        reconnectInterval = configInterval;

                    if (string.IsNullOrEmpty(ip) || string.IsNullOrEmpty(port))
                        if (string.IsNullOrEmpty(ip) || string.IsNullOrEmpty(port))
                        {
                            AddLog("配置信息不完整，无法连接到PLC");
                            await Task.Delay(RECONNECT_INTERVAL);

                            continue;
                        }

                    _tcpHelper = new TCPHelper(ip, port);
                    AddLog($"正在连接到 PLC: {ip}:{port}");

                    await _tcpHelper.Connect(
                        (datas, dataLength) =>
                        {
                            if (dataLength > 0)
                            {
                                Dispatcher.BeginInvoke(new Action(() =>
                                {
                                    try
                                    {
                                        RollerPLCProtocolMessage data = RollerPLCDataLogic.RollerPLCDataParse(datas);
                                        data.UpdateTime = DateTime.Now;
                                        AddDeviceData(data);
                                        AddLog(data);

                                        _isConnected = true; // 标记连接成功
                                    }
                                    catch (Exception ex)
                                    {
                                        AddLog(ex);
                                    }
                                }));
                            }
                        },
                        CancellationToken.None,
                        (ex) =>
                        {
                            Dispatcher.BeginInvoke(new Action(() =>
                            {
                                AddLog(new Exception("数据接收错误", ex));
                                _isConnected = false;
                            }));
                        }
                    );

                    AddLog("PLC 连接成功");

                    _isConnected = true;

                    return; // 连接成功，退出循环
                }
                catch (SocketException ex)
                {
                    _isConnected = false;
                    AddLog(new Exception("网络连接异常", ex));
                }
                catch (Exception ex)
                {
                    _isConnected = false;
                    AddLog(new Exception("连接失败", ex));
                }

                // 如果需要重连，等待后重试
                if (_shouldReconnect)
                {
                    AddLog($"连接失败，{reconnectInterval / 1000}秒后自动重连...");
                    try
                    {
                        _reconnectCancellationTokenSource = new CancellationTokenSource();
                        await Task.Delay(RECONNECT_INTERVAL, _reconnectCancellationTokenSource.Token);
                    }
                    catch (OperationCanceledException)
                    {
                        // 重连被取消
                        break;
                    }
                }
            }
        }

        #endregion

        #region 添加数据（先进后出）

        /// <summary>
        /// 添加数据（先进后出）
        /// </summary>
        /// <param name="data"></param>
        public void AddDeviceData(RollerPLCProtocolMessage data)
        {
            // 插入到开头
            _plcDataList.Insert(0, data);

            // 限制数量
            if (_plcDataList.Count > MAX_ITEMS)
                _plcDataList.RemoveAt(_plcDataList.Count - 1);
        }

        #endregion

        #region 日志方法

        /// <summary>
        /// 统一日志记录方法
        /// </summary>
        /// <param name="message">日志内容</param>
        public void AddLog(object message)
        {
            string logEntry = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] ";

            switch (message)
            {
                case RollerPLCProtocolMessage data:
                    logEntry += $"接收到数据: 设备号={data.DeviceId}, 任务号={data.TaskId}, 帧头={data.FrameHeader}";
                    break;
                case Exception ex:
                    string exceptionType = ex.GetType().Name;
                    logEntry += $"[{exceptionType}] 发生异常，原因是：{ex.Message}";
                    break;
                case string str:
                    logEntry += str;
                    break;
                default:
                    logEntry += message?.ToString() ?? "空消息";
                    break;
            }

            Dispatcher.BeginInvoke(new Action(() =>
            {
                if (logTextBox != null)
                {
                    logTextBox.AppendText(logEntry + Environment.NewLine);

                    // 限制日志行数
                    if (logTextBox.LineCount > MAX_LOG_LINES)
                    {
                        // 删除前几行以控制内存使用
                        int linesToRemove = logTextBox.LineCount - MAX_LOG_LINES;
                        int charsToRemove = logTextBox.GetCharacterIndexFromLineIndex(linesToRemove);
                        logTextBox.Text = logTextBox.Text.Substring(charsToRemove);
                    }

                    logTextBox.ScrollToEnd();
                }
            }));
        }

        #endregion

        #region 资源清理

        /// <summary>
        /// 清理资源
        /// </summary>
        private void Cleanup()
        {
            try
            {
                _tcpHelper?.Disconnect();
                _isConnected = false;
            }
            catch (Exception ex)
            {
                AddLog(new Exception("断开连接时发生错误", ex));
            }
        }

        #endregion
    }
}